{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "# work in progress"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# TODO\n",
    "\n",
    "# General\n",
    "\n",
    "# Exploratory Data Analysis\n",
    "# check out https://github.com/salesforce/Merlion for anomaly detection\n",
    "# check out MNE: https://mne.tools/stable/index.html\n",
    "\n",
    "# Time series packages\n",
    "# - tsfresh\n",
    "# - tslearn \n",
    "# - pyts\n",
    "# - sktime\n",
    "# - aeon \n",
    "# - tsai\n",
    "# - darts\n",
    "# - merlion\n",
    "# - https://github.com/thuml/Time-Series-Library\n",
    "\n",
    "\n",
    "# Preprocessing \n",
    "# - for eeg check out mne: https://mne.tools/stable/index.html and https://github.com/sappelhoff/pyprep\n",
    "# - find a sampling frequency that is high enough to capture the relevant information\n",
    "#  -> thiam et al. 2021: 256 Hz, take a look at section 3.5 for more information and additional steps\n",
    "# see https://pyts.readthedocs.io/en/stable/auto_examples/preprocessing/plot_scalers.html#sphx-glr-auto-examples-preprocessing-plot-scalers-py\n",
    "# add group standardization? or just use robust scaler?\n",
    "# -> could be important for transfer learning\n",
    "# https://stackoverflow.com/questions/55601928/apply-multiple-standardscalers-to-individual-groups\n",
    "\n",
    "# Data\n",
    "# handling imbalanced data\n",
    "#   - https://github.com/scikit-learn-contrib/imbalanced-learn\n",
    "#   - https://www.tensorflow.org/tutorials/structured_data/imbalanced_data\n",
    "#   - oversampling the minority class, undersampling the majority class\n",
    "#   - imblearn.over_sampling import RandomOverSampler\n",
    "#   - SMOTE? https://www.analyticsvidhya.com/blog/2020/10/overcoming-class-imbalance-using-smote-techniques/\n",
    "#   -> quite controversial according to some guy on twitter\n",
    "#   - https://www.tensorflow.org/tutorials/structured_data/imbalanced_data#class_weights\n",
    "#   - https://twitter.com/predict_addict/status/1700467528969879886\n",
    "# synthetic data generation\n",
    "#   - TabDDPM: Modelling Tabular Data with Diffusion Models, https://arxiv.org/abs/2209.15421\n",
    "#   - also see raschkas books\n",
    "# self supervised learning (again raschka)\n",
    "#   - must read https://www.techrxiv.org/articles/preprint/Applications_of_Self-Supervised_Learning_to_Biomedical_Signals_where_are_we_now/22567021/1/files/40045018.pdf\n",
    "\n",
    "# Labels\n",
    "# check out https://dl.acm.org/doi/abs/10.1145/3555776.3577721\n",
    "\n",
    "# Skorch\n",
    "# Define callbacks\n",
    "#  - https://skorch.readthedocs.io/en/stable/callbacks.html\n",
    "#  - email reminder for training\n",
    "# take a look into basic usage notebook from the skorch documentation\n",
    "# also check out mlflow for logging: https://mlflow.org/docs/latest/tracking.html\n",
    "# change the path to the tensorboard logs (runs folder)\n",
    "# check if softmax with default nll-criterion gives the same result as cross-entropy loss (it should)\n",
    "#  -> bad idea for implementation, always use high level functions\n",
    "\n",
    "# Models\n",
    "# systematic literature review: Automatic assessment of pain based on deep learning methods\n",
    "# correct input parameters for the models (see commented code underneath the model definition)\n",
    "#   -> find out how this works with skorch, does it take input parameters from the model definition?\n",
    "# add nn.Flatten() to the beginning of the MLP, simplify pipeline. maybe. or don't. doesn't have to be perfect.\n",
    "#   - note that torch.flatten is not in Fortran order, so the resulting tensor is not contiguous\n",
    "#   -> better question: does this change the performance of the model? (for CNNs pretty sure it does)\n",
    "# and sktime\n",
    "# add CatBoost\n",
    "#  -> try to explain the model, e.g. with SHAP & boruta shap https://github.com/Ekeany/Boruta-Shap\n",
    "#  -> also https://github.com/cerlymarco/shap-hypetune\n",
    "# add MOS-CNN from https://github.com/Wensi-Tang/OS-CNN\n",
    "# add CNN-LSTM\n",
    "# add MLSTM-FCN from https://github.com/alexmelekhin/MLSTM-FCN-Pytorch\n",
    "# time gpt: https://arxiv.org/abs/2310.03589 and https://news.ycombinator.com/item?id=37874891\n",
    "# - https://github.com/thuml/Time-Series-Library\n",
    "\n",
    "# Models (later on)\n",
    "# remain sceptical of architectures that are not specifically designed for time series classification\n",
    "# remain sceptical of transformers for now \n",
    "# take a deep dive: https://robjhyndman.com/hyndsight/python_time_series.html\n",
    "# note that pytorch-forecasting can easily be used for classification\n",
    "#   - https://pytorch-forecasting.readthedocs.io/en/stable/tutorials/building.html#Classification\n",
    "#   - https://pytorch-forecasting.readthedocs.io/en/stable/models.html\n",
    "#   -> work through both sites\n",
    "# also darts: https://unit8co.github.io/darts/index.html\n",
    "# and https://github.com/timeseriesAI/tsai\n",
    "# add TemporalFusionTransformer (later on)\n",
    "#   - may be not possible\n",
    "#   - also see https://stackoverflow.com/questions/76313665/classification-in-pytorch-forecastings-temporal-fusion-transformer\n",
    "# add TodyNet (later on)\n",
    "#   - quite complicated\n",
    "#   - Q: the graph is nice for explaining the model, but will it be used if it does not compete with the best model?\n",
    "# do not use ensemble models for now because they can be too slow in inference for real-time applications and not very interpretable\n",
    "#   - although, some argue for the opposite: https://ai.googleblog.com/2021/11/model-ensembles-are-faster-than-you.html\n",
    "# also, neural networks could be faster in inference than random forests, https://stats.stackexchange.com/a/216126\n",
    "# try out pyts for time series classification\n",
    "# https://www.statsmodels.org/stable/tsa.html\n",
    "# pingouin\n",
    "\n",
    "# Training\n",
    "# check out pycaret first: https://pycaret.org/ to get an overview of what to do / the whole pipeline\n",
    "# use randomizedgridsearch?: https://scikit-learn.org/stable/modules/grid_search.html#grid-search\n",
    "# check out optuna: https://optuna.org/,\n",
    "#   - skorch code: https://github.com/optuna/optuna-examples/blob/main/pytorch/skorch_simple.py\n",
    "#   - paper: https://arxiv.org/pdf/1907.10902.pdf\n",
    "# also check out ray tune: https://docs.ray.io/en/master/tune/index.html\n",
    "#  - https://docs.ray.io/en/master/tune/tutorials/tune-sklearn.html\n",
    "# and bayesian optimization for hyperparameter tuning: botorch in optuna?\n",
    "# - check out https://github.com/pyRiemann/pyRiemann\n",
    "# https://huggingface.co/autotrain\n",
    "\n",
    "# Inference\n",
    "# - winning lottery ticket hypothesis: https://arxiv.org/pdf/1803.03635.pdf\n",
    "# - try pruning to reduce model size and latency: https://pytorch.org/tutorials/intermediate/pruning_tutorial.html\n",
    "\n",
    "# XAI\n",
    "# https://arxiv.org/pdf/2104.00950.pdf\n",
    "# feature selection, feature extraction, feature importance, ...\n",
    "# https://captum.ai/\n",
    "# model agnostic methods like SHAP, LIME, \n",
    "#   - go through https://christophm.github.io/interpretable-ml-book/\n",
    "#   - https://github.com/christophM/shap-book\n",
    "#   - also read SHAPELY paper: https://arxiv.org/pdf/1705.07874.pdf\n",
    "# This could be a perfect fit?!\n",
    "#   - must read: https://arxiv.org/pdf/2208.05280.pdf\n",
    "#   - code: https://github.com/fzi-forschungszentrum-informatik/TSInterpret \n",
    "#   - overview: https://joss.theoj.org/papers/10.21105/joss.05220\n",
    "\n",
    "# Model Comparison\n",
    "# see Raschkas paper section 4 for different ways / metrics https://arxiv.org/pdf/1811.12808.pdf\n",
    "# plus MLxtend\n",
    "\n",
    "# Deployment\n",
    "# take a look at https://github.com/skops-dev/skops\n",
    "\n",
    "# NOTE:\n",
    "# don't just delete stuff from the todo list, put them in the done list here for now (+ git commit message)\n",
    "\n",
    "# DONE\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import sys\n",
    "from pathlib import Path\n",
    "PROJECT_DIR = Path.cwd()\n",
    "if PROJECT_DIR.stem == 'notebooks':\n",
    "    PROJECT_DIR = PROJECT_DIR.parent\n",
    "    sys.path.insert(0, '..')\n",
    "    %load_ext autoreload\n",
    "    %autoreload 2\n",
    "    "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "torch.__version__ = '2.0.1'\n",
      "torch.cuda.is_available() = False\n"
     ]
    }
   ],
   "source": [
    "import importlib\n",
    "\n",
    "import pandas as pd\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "import torch\n",
    "from torch import nn\n",
    "from skorch import NeuralNetClassifier\n",
    "from skorch.callbacks import TensorBoard\n",
    "from torch.utils.tensorboard import SummaryWriter\n",
    "\n",
    "from sklearn.preprocessing import FunctionTransformer\n",
    "from sklearn.pipeline import make_pipeline\n",
    "from sklearn.model_selection import GroupKFold, cross_val_score\n",
    "\n",
    "\n",
    "from sklearn.metrics import (\n",
    "    accuracy_score,\n",
    "    matthews_corrcoef, \n",
    "    confusion_matrix, \n",
    "    ConfusionMatrixDisplay\n",
    "    )\n",
    "\n",
    "print(f\"{torch.__version__ = }\")\n",
    "print(f\"{torch.cuda.is_available() = }\")\n",
    "\n",
    "from src.features.scalers_3d import StandardScaler3D, MinMaxScaler3D, RobustScaler3D, MaxAbsScaler3D\n",
    "from src.features.reshape_features_to_2d import reshape_features_to_2D\n",
    "\n",
    "DATA_DIR = PROJECT_DIR / 'data' / 'dummy'\n",
    "MODEL_DIR = PROJECT_DIR / 'models' / 'dummy'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "\n",
    "writer = SummaryWriter()\n",
    "callbacks = []\n",
    "callbacks.append(TensorBoard(writer))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Define MLP in pytorch\n",
    "class MultiLayerPerceptron(nn.Module):\n",
    "    def __init__(self, num_units=100):\n",
    "        super().__init__()\n",
    "\n",
    "        self.dense0 = nn.Linear(data.shape[1]*data.shape[2], num_units)\n",
    "        self.nonlin = nn.ReLU()\n",
    "        self.dropout = nn.Dropout(0.5)\n",
    "        self.dense1 = nn.Linear(num_units, num_units)\n",
    "        self.output = nn.Linear(num_units, 2)\n",
    "        self.softmax = nn.Softmax(dim=-1)\n",
    "\n",
    "    def forward(self, X, **kwargs):\n",
    "        X = self.nonlin(self.dense0(X))\n",
    "        X = self.dropout(X)\n",
    "        X = self.nonlin(self.dense1(X))\n",
    "        X = self.softmax(self.output(X))\n",
    "        return X\n",
    "    \n",
    "\"\"\"\n",
    "# Create a model with non-linear and linear layers\n",
    "class FashionMNISTModelV1(nn.Module):\n",
    "    def __init__(self, input_shape: int, hidden_units: int, output_shape: int):\n",
    "        super().__init__()\n",
    "        self.layer_stack = nn.Sequential(\n",
    "            nn.Flatten(), # flatten inputs into single vector\n",
    "            nn.Linear(in_features=input_shape, out_features=hidden_units),\n",
    "            nn.ReLU(),\n",
    "            nn.Linear(in_features=hidden_units, out_features=output_shape),\n",
    "            nn.ReLU()\n",
    "        )\n",
    "    \n",
    "    def forward(self, x: torch.Tensor):\n",
    "        return self.layer_stack(x)\n",
    "\"\"\"\n",
    "\n",
    "# Create MLP with skorch\n",
    "mlp = NeuralNetClassifier(\n",
    "    MultiLayerPerceptron,\n",
    "    max_epochs=10,\n",
    "    lr=0.1,\n",
    "    # Shuffle training data on each epoch\n",
    "    iterator_train__shuffle=True,\n",
    "    callbacks=callbacks\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Define LSTM with pytorch\n",
    "class LongShortTermMemory(nn.Module):\n",
    "    def __init__(self, num_units=10):\n",
    "        super().__init__()\n",
    "\n",
    "        self.lstm = nn.LSTM(\n",
    "            input_size=data.shape[2],\n",
    "            hidden_size=num_units,\n",
    "            num_layers=1,\n",
    "            batch_first=True\n",
    "        )\n",
    "        self.output = nn.Linear(num_units, 2)\n",
    "        self.softmax = nn.Softmax(dim=-1)\n",
    "\n",
    "    def forward(self, X, **kwargs):\n",
    "        X, _ = self.lstm(X)\n",
    "        X = self.softmax(self.output(X[:, -1, :]))\n",
    "        return X\n",
    "\n",
    "\n",
    "# Create LSTM with skorch\n",
    "lstm = NeuralNetClassifier(\n",
    "    LongShortTermMemory,\n",
    "    max_epochs=10,\n",
    "    lr=0.1,\n",
    "    # Shuffle training data on each epoch\n",
    "    iterator_train__shuffle=True,\n",
    "    callbacks=callbacks\n",
    ")\n",
    "\n",
    "\n"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Load data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "data.shape = (4000, 500, 3)\n",
      "target.shape = (4000,)\n",
      "groups.shape = (4000,)\n"
     ]
    }
   ],
   "source": [
    "\n",
    "data = np.load(DATA_DIR / \"data.npy\").astype(np.float32)\n",
    "target = np.load(DATA_DIR / \"target.npy\").astype(np.int64)\n",
    "groups = np.load(DATA_DIR / \"groups.npy\").astype(np.int64)\n",
    "\n",
    "print(f\"{data.shape = }\\n{target.shape = }\\n{groups.shape = }\")\n"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Modeling"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Create pipelines with sklearn\n",
    "mlp_pipe = make_pipeline(\n",
    "    StandardScaler3D(),\n",
    "    FunctionTransformer(reshape_features_to_2D), \n",
    "    mlp)\n",
    "\n",
    "lstm_pipe = make_pipeline(\n",
    "    MinMaxScaler3D(),\n",
    "    lstm)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "  epoch    train_loss    valid_acc    valid_loss     dur\n",
      "-------  ------------  -----------  ------------  ------\n",
      "      1        \u001b[36m0.4268\u001b[0m       \u001b[32m0.8300\u001b[0m        \u001b[35m0.2952\u001b[0m  0.2084\n",
      "      2        \u001b[36m0.3573\u001b[0m       0.7725        0.3045  0.1546\n",
      "      3        \u001b[36m0.3523\u001b[0m       0.8037        \u001b[35m0.2928\u001b[0m  0.1546\n",
      "      4        \u001b[36m0.3477\u001b[0m       0.8237        \u001b[35m0.2874\u001b[0m  0.1685\n",
      "      5        0.3487       0.8263        0.2892  0.1496\n",
      "      6        \u001b[36m0.3450\u001b[0m       0.8113        0.2909  0.1496\n",
      "      7        \u001b[36m0.3439\u001b[0m       0.8100        0.2898  0.1626\n",
      "      8        0.3446       0.7738        0.3029  0.1336\n",
      "      9        0.3456       \u001b[32m0.8313\u001b[0m        0.2882  0.1526\n",
      "     10        0.3448       0.7850        0.2943  0.1486\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<style>#sk-container-id-1 {color: black;background-color: white;}#sk-container-id-1 pre{padding: 0;}#sk-container-id-1 div.sk-toggleable {background-color: white;}#sk-container-id-1 label.sk-toggleable__label {cursor: pointer;display: block;width: 100%;margin-bottom: 0;padding: 0.3em;box-sizing: border-box;text-align: center;}#sk-container-id-1 label.sk-toggleable__label-arrow:before {content: \"▸\";float: left;margin-right: 0.25em;color: #696969;}#sk-container-id-1 label.sk-toggleable__label-arrow:hover:before {color: black;}#sk-container-id-1 div.sk-estimator:hover label.sk-toggleable__label-arrow:before {color: black;}#sk-container-id-1 div.sk-toggleable__content {max-height: 0;max-width: 0;overflow: hidden;text-align: left;background-color: #f0f8ff;}#sk-container-id-1 div.sk-toggleable__content pre {margin: 0.2em;color: black;border-radius: 0.25em;background-color: #f0f8ff;}#sk-container-id-1 input.sk-toggleable__control:checked~div.sk-toggleable__content {max-height: 200px;max-width: 100%;overflow: auto;}#sk-container-id-1 input.sk-toggleable__control:checked~label.sk-toggleable__label-arrow:before {content: \"▾\";}#sk-container-id-1 div.sk-estimator input.sk-toggleable__control:checked~label.sk-toggleable__label {background-color: #d4ebff;}#sk-container-id-1 div.sk-label input.sk-toggleable__control:checked~label.sk-toggleable__label {background-color: #d4ebff;}#sk-container-id-1 input.sk-hidden--visually {border: 0;clip: rect(1px 1px 1px 1px);clip: rect(1px, 1px, 1px, 1px);height: 1px;margin: -1px;overflow: hidden;padding: 0;position: absolute;width: 1px;}#sk-container-id-1 div.sk-estimator {font-family: monospace;background-color: #f0f8ff;border: 1px dotted black;border-radius: 0.25em;box-sizing: border-box;margin-bottom: 0.5em;}#sk-container-id-1 div.sk-estimator:hover {background-color: #d4ebff;}#sk-container-id-1 div.sk-parallel-item::after {content: \"\";width: 100%;border-bottom: 1px solid gray;flex-grow: 1;}#sk-container-id-1 div.sk-label:hover label.sk-toggleable__label {background-color: #d4ebff;}#sk-container-id-1 div.sk-serial::before {content: \"\";position: absolute;border-left: 1px solid gray;box-sizing: border-box;top: 0;bottom: 0;left: 50%;z-index: 0;}#sk-container-id-1 div.sk-serial {display: flex;flex-direction: column;align-items: center;background-color: white;padding-right: 0.2em;padding-left: 0.2em;position: relative;}#sk-container-id-1 div.sk-item {position: relative;z-index: 1;}#sk-container-id-1 div.sk-parallel {display: flex;align-items: stretch;justify-content: center;background-color: white;position: relative;}#sk-container-id-1 div.sk-item::before, #sk-container-id-1 div.sk-parallel-item::before {content: \"\";position: absolute;border-left: 1px solid gray;box-sizing: border-box;top: 0;bottom: 0;left: 50%;z-index: -1;}#sk-container-id-1 div.sk-parallel-item {display: flex;flex-direction: column;z-index: 1;position: relative;background-color: white;}#sk-container-id-1 div.sk-parallel-item:first-child::after {align-self: flex-end;width: 50%;}#sk-container-id-1 div.sk-parallel-item:last-child::after {align-self: flex-start;width: 50%;}#sk-container-id-1 div.sk-parallel-item:only-child::after {width: 0;}#sk-container-id-1 div.sk-dashed-wrapped {border: 1px dashed gray;margin: 0 0.4em 0.5em 0.4em;box-sizing: border-box;padding-bottom: 0.4em;background-color: white;}#sk-container-id-1 div.sk-label label {font-family: monospace;font-weight: bold;display: inline-block;line-height: 1.2em;}#sk-container-id-1 div.sk-label-container {text-align: center;}#sk-container-id-1 div.sk-container {/* jupyter's `normalize.less` sets `[hidden] { display: none; }` but bootstrap.min.css set `[hidden] { display: none !important; }` so we also need the `!important` here to be able to override the default hidden behavior on the sphinx rendered scikit-learn.org. See: https://github.com/scikit-learn/scikit-learn/issues/21755 */display: inline-block !important;position: relative;}#sk-container-id-1 div.sk-text-repr-fallback {display: none;}</style><div id=\"sk-container-id-1\" class=\"sk-top-container\"><div class=\"sk-text-repr-fallback\"><pre>Pipeline(steps=[(&#x27;standardscaler3d&#x27;, StandardScaler3D()),\n",
       "                (&#x27;functiontransformer&#x27;,\n",
       "                 FunctionTransformer(func=&lt;function reshape_features_to_2D at 0x00000232CF4E3010&gt;)),\n",
       "                (&#x27;neuralnetclassifier&#x27;,\n",
       "                 &lt;class &#x27;skorch.classifier.NeuralNetClassifier&#x27;&gt;[initialized](\n",
       "  module_=MultiLayerPerceptron(\n",
       "    (dense0): Linear(in_features=1500, out_features=100, bias=True)\n",
       "    (nonlin): ReLU()\n",
       "    (dropout): Dropout(p=0.5, inplace=False)\n",
       "    (dense1): Linear(in_features=100, out_features=100, bias=True)\n",
       "    (output): Linear(in_features=100, out_features=2, bias=True)\n",
       "    (softmax): Softmax(dim=-1)\n",
       "  ),\n",
       "))])</pre><b>In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook. <br />On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.</b></div><div class=\"sk-container\" hidden><div class=\"sk-item sk-dashed-wrapped\"><div class=\"sk-label-container\"><div class=\"sk-label sk-toggleable\"><input class=\"sk-toggleable__control sk-hidden--visually\" id=\"sk-estimator-id-1\" type=\"checkbox\" ><label for=\"sk-estimator-id-1\" class=\"sk-toggleable__label sk-toggleable__label-arrow\">Pipeline</label><div class=\"sk-toggleable__content\"><pre>Pipeline(steps=[(&#x27;standardscaler3d&#x27;, StandardScaler3D()),\n",
       "                (&#x27;functiontransformer&#x27;,\n",
       "                 FunctionTransformer(func=&lt;function reshape_features_to_2D at 0x00000232CF4E3010&gt;)),\n",
       "                (&#x27;neuralnetclassifier&#x27;,\n",
       "                 &lt;class &#x27;skorch.classifier.NeuralNetClassifier&#x27;&gt;[initialized](\n",
       "  module_=MultiLayerPerceptron(\n",
       "    (dense0): Linear(in_features=1500, out_features=100, bias=True)\n",
       "    (nonlin): ReLU()\n",
       "    (dropout): Dropout(p=0.5, inplace=False)\n",
       "    (dense1): Linear(in_features=100, out_features=100, bias=True)\n",
       "    (output): Linear(in_features=100, out_features=2, bias=True)\n",
       "    (softmax): Softmax(dim=-1)\n",
       "  ),\n",
       "))])</pre></div></div></div><div class=\"sk-serial\"><div class=\"sk-item\"><div class=\"sk-estimator sk-toggleable\"><input class=\"sk-toggleable__control sk-hidden--visually\" id=\"sk-estimator-id-2\" type=\"checkbox\" ><label for=\"sk-estimator-id-2\" class=\"sk-toggleable__label sk-toggleable__label-arrow\">StandardScaler3D</label><div class=\"sk-toggleable__content\"><pre>StandardScaler3D()</pre></div></div></div><div class=\"sk-item\"><div class=\"sk-estimator sk-toggleable\"><input class=\"sk-toggleable__control sk-hidden--visually\" id=\"sk-estimator-id-3\" type=\"checkbox\" ><label for=\"sk-estimator-id-3\" class=\"sk-toggleable__label sk-toggleable__label-arrow\">FunctionTransformer</label><div class=\"sk-toggleable__content\"><pre>FunctionTransformer(func=&lt;function reshape_features_to_2D at 0x00000232CF4E3010&gt;)</pre></div></div></div><div class=\"sk-item\"><div class=\"sk-estimator sk-toggleable\"><input class=\"sk-toggleable__control sk-hidden--visually\" id=\"sk-estimator-id-4\" type=\"checkbox\" ><label for=\"sk-estimator-id-4\" class=\"sk-toggleable__label sk-toggleable__label-arrow\">NeuralNetClassifier</label><div class=\"sk-toggleable__content\"><pre>&lt;class &#x27;skorch.classifier.NeuralNetClassifier&#x27;&gt;[initialized](\n",
       "  module_=MultiLayerPerceptron(\n",
       "    (dense0): Linear(in_features=1500, out_features=100, bias=True)\n",
       "    (nonlin): ReLU()\n",
       "    (dropout): Dropout(p=0.5, inplace=False)\n",
       "    (dense1): Linear(in_features=100, out_features=100, bias=True)\n",
       "    (output): Linear(in_features=100, out_features=2, bias=True)\n",
       "    (softmax): Softmax(dim=-1)\n",
       "  ),\n",
       ")</pre></div></div></div></div></div></div></div>"
      ],
      "text/plain": [
       "Pipeline(steps=[('standardscaler3d', StandardScaler3D()),\n",
       "                ('functiontransformer',\n",
       "                 FunctionTransformer(func=<function reshape_features_to_2D at 0x00000232CF4E3010>)),\n",
       "                ('neuralnetclassifier',\n",
       "                 <class 'skorch.classifier.NeuralNetClassifier'>[initialized](\n",
       "  module_=MultiLayerPerceptron(\n",
       "    (dense0): Linear(in_features=1500, out_features=100, bias=True)\n",
       "    (nonlin): ReLU()\n",
       "    (dropout): Dropout(p=0.5, inplace=False)\n",
       "    (dense1): Linear(in_features=100, out_features=100, bias=True)\n",
       "    (output): Linear(in_features=100, out_features=2, bias=True)\n",
       "    (softmax): Softmax(dim=-1)\n",
       "  ),\n",
       "))])"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "mlp_pipe.fit(data, target)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "  epoch    train_loss    valid_acc    valid_loss     dur\n",
      "-------  ------------  -----------  ------------  ------\n",
      "      1        \u001b[36m0.6921\u001b[0m       \u001b[32m0.6550\u001b[0m        \u001b[35m0.6883\u001b[0m  2.2476\n",
      "      2        \u001b[36m0.6871\u001b[0m       \u001b[32m0.7638\u001b[0m        \u001b[35m0.6817\u001b[0m  2.1812\n",
      "      3        \u001b[36m0.6806\u001b[0m       0.7500        \u001b[35m0.6730\u001b[0m  2.1839\n",
      "      4        \u001b[36m0.6714\u001b[0m       \u001b[32m0.7825\u001b[0m        \u001b[35m0.6597\u001b[0m  2.1610\n",
      "      5        \u001b[36m0.6564\u001b[0m       0.7550        \u001b[35m0.6362\u001b[0m  2.1294\n",
      "      6        \u001b[36m0.6267\u001b[0m       0.7500        \u001b[35m0.5869\u001b[0m  2.1862\n",
      "      7        \u001b[36m0.5590\u001b[0m       0.7562        \u001b[35m0.4799\u001b[0m  2.0195\n",
      "      8        \u001b[36m0.4840\u001b[0m       \u001b[32m0.8250\u001b[0m        \u001b[35m0.4100\u001b[0m  1.7523\n",
      "      9        \u001b[36m0.4506\u001b[0m       0.8250        \u001b[35m0.3774\u001b[0m  1.7603\n",
      "     10        \u001b[36m0.4312\u001b[0m       0.8063        \u001b[35m0.3633\u001b[0m  1.7906\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<style>#sk-container-id-2 {color: black;background-color: white;}#sk-container-id-2 pre{padding: 0;}#sk-container-id-2 div.sk-toggleable {background-color: white;}#sk-container-id-2 label.sk-toggleable__label {cursor: pointer;display: block;width: 100%;margin-bottom: 0;padding: 0.3em;box-sizing: border-box;text-align: center;}#sk-container-id-2 label.sk-toggleable__label-arrow:before {content: \"▸\";float: left;margin-right: 0.25em;color: #696969;}#sk-container-id-2 label.sk-toggleable__label-arrow:hover:before {color: black;}#sk-container-id-2 div.sk-estimator:hover label.sk-toggleable__label-arrow:before {color: black;}#sk-container-id-2 div.sk-toggleable__content {max-height: 0;max-width: 0;overflow: hidden;text-align: left;background-color: #f0f8ff;}#sk-container-id-2 div.sk-toggleable__content pre {margin: 0.2em;color: black;border-radius: 0.25em;background-color: #f0f8ff;}#sk-container-id-2 input.sk-toggleable__control:checked~div.sk-toggleable__content {max-height: 200px;max-width: 100%;overflow: auto;}#sk-container-id-2 input.sk-toggleable__control:checked~label.sk-toggleable__label-arrow:before {content: \"▾\";}#sk-container-id-2 div.sk-estimator input.sk-toggleable__control:checked~label.sk-toggleable__label {background-color: #d4ebff;}#sk-container-id-2 div.sk-label input.sk-toggleable__control:checked~label.sk-toggleable__label {background-color: #d4ebff;}#sk-container-id-2 input.sk-hidden--visually {border: 0;clip: rect(1px 1px 1px 1px);clip: rect(1px, 1px, 1px, 1px);height: 1px;margin: -1px;overflow: hidden;padding: 0;position: absolute;width: 1px;}#sk-container-id-2 div.sk-estimator {font-family: monospace;background-color: #f0f8ff;border: 1px dotted black;border-radius: 0.25em;box-sizing: border-box;margin-bottom: 0.5em;}#sk-container-id-2 div.sk-estimator:hover {background-color: #d4ebff;}#sk-container-id-2 div.sk-parallel-item::after {content: \"\";width: 100%;border-bottom: 1px solid gray;flex-grow: 1;}#sk-container-id-2 div.sk-label:hover label.sk-toggleable__label {background-color: #d4ebff;}#sk-container-id-2 div.sk-serial::before {content: \"\";position: absolute;border-left: 1px solid gray;box-sizing: border-box;top: 0;bottom: 0;left: 50%;z-index: 0;}#sk-container-id-2 div.sk-serial {display: flex;flex-direction: column;align-items: center;background-color: white;padding-right: 0.2em;padding-left: 0.2em;position: relative;}#sk-container-id-2 div.sk-item {position: relative;z-index: 1;}#sk-container-id-2 div.sk-parallel {display: flex;align-items: stretch;justify-content: center;background-color: white;position: relative;}#sk-container-id-2 div.sk-item::before, #sk-container-id-2 div.sk-parallel-item::before {content: \"\";position: absolute;border-left: 1px solid gray;box-sizing: border-box;top: 0;bottom: 0;left: 50%;z-index: -1;}#sk-container-id-2 div.sk-parallel-item {display: flex;flex-direction: column;z-index: 1;position: relative;background-color: white;}#sk-container-id-2 div.sk-parallel-item:first-child::after {align-self: flex-end;width: 50%;}#sk-container-id-2 div.sk-parallel-item:last-child::after {align-self: flex-start;width: 50%;}#sk-container-id-2 div.sk-parallel-item:only-child::after {width: 0;}#sk-container-id-2 div.sk-dashed-wrapped {border: 1px dashed gray;margin: 0 0.4em 0.5em 0.4em;box-sizing: border-box;padding-bottom: 0.4em;background-color: white;}#sk-container-id-2 div.sk-label label {font-family: monospace;font-weight: bold;display: inline-block;line-height: 1.2em;}#sk-container-id-2 div.sk-label-container {text-align: center;}#sk-container-id-2 div.sk-container {/* jupyter's `normalize.less` sets `[hidden] { display: none; }` but bootstrap.min.css set `[hidden] { display: none !important; }` so we also need the `!important` here to be able to override the default hidden behavior on the sphinx rendered scikit-learn.org. See: https://github.com/scikit-learn/scikit-learn/issues/21755 */display: inline-block !important;position: relative;}#sk-container-id-2 div.sk-text-repr-fallback {display: none;}</style><div id=\"sk-container-id-2\" class=\"sk-top-container\"><div class=\"sk-text-repr-fallback\"><pre>Pipeline(steps=[(&#x27;minmaxscaler3d&#x27;, MinMaxScaler3D()),\n",
       "                (&#x27;neuralnetclassifier&#x27;,\n",
       "                 &lt;class &#x27;skorch.classifier.NeuralNetClassifier&#x27;&gt;[initialized](\n",
       "  module_=LongShortTermMemory(\n",
       "    (lstm): LSTM(3, 10, batch_first=True)\n",
       "    (output): Linear(in_features=10, out_features=2, bias=True)\n",
       "    (softmax): Softmax(dim=-1)\n",
       "  ),\n",
       "))])</pre><b>In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook. <br />On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.</b></div><div class=\"sk-container\" hidden><div class=\"sk-item sk-dashed-wrapped\"><div class=\"sk-label-container\"><div class=\"sk-label sk-toggleable\"><input class=\"sk-toggleable__control sk-hidden--visually\" id=\"sk-estimator-id-5\" type=\"checkbox\" ><label for=\"sk-estimator-id-5\" class=\"sk-toggleable__label sk-toggleable__label-arrow\">Pipeline</label><div class=\"sk-toggleable__content\"><pre>Pipeline(steps=[(&#x27;minmaxscaler3d&#x27;, MinMaxScaler3D()),\n",
       "                (&#x27;neuralnetclassifier&#x27;,\n",
       "                 &lt;class &#x27;skorch.classifier.NeuralNetClassifier&#x27;&gt;[initialized](\n",
       "  module_=LongShortTermMemory(\n",
       "    (lstm): LSTM(3, 10, batch_first=True)\n",
       "    (output): Linear(in_features=10, out_features=2, bias=True)\n",
       "    (softmax): Softmax(dim=-1)\n",
       "  ),\n",
       "))])</pre></div></div></div><div class=\"sk-serial\"><div class=\"sk-item\"><div class=\"sk-estimator sk-toggleable\"><input class=\"sk-toggleable__control sk-hidden--visually\" id=\"sk-estimator-id-6\" type=\"checkbox\" ><label for=\"sk-estimator-id-6\" class=\"sk-toggleable__label sk-toggleable__label-arrow\">MinMaxScaler3D</label><div class=\"sk-toggleable__content\"><pre>MinMaxScaler3D()</pre></div></div></div><div class=\"sk-item\"><div class=\"sk-estimator sk-toggleable\"><input class=\"sk-toggleable__control sk-hidden--visually\" id=\"sk-estimator-id-7\" type=\"checkbox\" ><label for=\"sk-estimator-id-7\" class=\"sk-toggleable__label sk-toggleable__label-arrow\">NeuralNetClassifier</label><div class=\"sk-toggleable__content\"><pre>&lt;class &#x27;skorch.classifier.NeuralNetClassifier&#x27;&gt;[initialized](\n",
       "  module_=LongShortTermMemory(\n",
       "    (lstm): LSTM(3, 10, batch_first=True)\n",
       "    (output): Linear(in_features=10, out_features=2, bias=True)\n",
       "    (softmax): Softmax(dim=-1)\n",
       "  ),\n",
       ")</pre></div></div></div></div></div></div></div>"
      ],
      "text/plain": [
       "Pipeline(steps=[('minmaxscaler3d', MinMaxScaler3D()),\n",
       "                ('neuralnetclassifier',\n",
       "                 <class 'skorch.classifier.NeuralNetClassifier'>[initialized](\n",
       "  module_=LongShortTermMemory(\n",
       "    (lstm): LSTM(3, 10, batch_first=True)\n",
       "    (output): Linear(in_features=10, out_features=2, bias=True)\n",
       "    (softmax): Softmax(dim=-1)\n",
       "  ),\n",
       "))])"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "lstm_pipe.fit(data, target)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Test data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "data_test.shape = (800, 500, 3)\n",
      "target_test.shape = (800,)\n"
     ]
    }
   ],
   "source": [
    "# Load data\n",
    "data_test = np.load(DATA_DIR / \"data_test.npy\").astype(np.float32)\n",
    "target_test = np.load(DATA_DIR / \"target_test.npy\").astype(np.float32)\n",
    "\n",
    "print(f\"{data_test.shape = }\\n{target_test.shape = }\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Metrics for MLP classifier:\n",
      "acc = 0.67375\n",
      "mcc = 0.3919382392457072\n"
     ]
    },
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 640x480 with 2 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Metrics for MLP classifier\n",
    "\n",
    "target_predicted = mlp_pipe.predict(data_test)\n",
    "\n",
    "cm = confusion_matrix(target_test, target_predicted)\n",
    "acc = accuracy_score(target_test, target_predicted)\n",
    "mcc = matthews_corrcoef(target_test, target_predicted)\n",
    "\n",
    "ConfusionMatrixDisplay(\n",
    "    confusion_matrix=cm, \n",
    "    display_labels=mlp_pipe.classes_,\n",
    "    ).plot()\n",
    "\n",
    "print(\"Metrics for MLP classifier:\")\n",
    "print(f\"{acc = }\\n{mcc = }\")\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "mlp_score = 0.67375\n",
      "lstm_score = 0.68625\n"
     ]
    }
   ],
   "source": [
    "mlp_score = mlp_pipe.score(data_test, target_test)\n",
    "print(f\"{mlp_score = }\")\n",
    "\n",
    "lstm_score = lstm_pipe.score(data_test, target_test)\n",
    "print(f\"{lstm_score = }\")\n"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "scores on the test data are much lower than on the train data -> the model clearly overfits non-grouped data"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# GroupKFold cross-validation \n",
    "(doing it right)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "The average accuracy is 0.764 ± 0.029\n"
     ]
    }
   ],
   "source": [
    "cv = GroupKFold(n_splits=5)\n",
    "test_score = cross_val_score(\n",
    "    mlp_pipe,\n",
    "    data, target,\n",
    "    groups=groups,\n",
    "    cv=cv,\n",
    "    n_jobs=5)\n",
    "print(f\"The average accuracy is \"\n",
    "      f\"{test_score.mean():.3f} ± \"\n",
    "      f\"{test_score.std():.3f}\")\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([0.7425 , 0.74625, 0.725  , 0.8    , 0.75   ])"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "test_score"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "The average accuracy is 0.753 ± 0.025\n"
     ]
    }
   ],
   "source": [
    "cv = GroupKFold()\n",
    "test_score = cross_val_score(\n",
    "    lstm_pipe,\n",
    "    data, \n",
    "    target, \n",
    "    groups=groups,\n",
    "    cv=cv, \n",
    "    n_jobs=5)\n",
    "print(f\"The average accuracy is \"\n",
    "      f\"{test_score.mean():.3f} ± \"\n",
    "      f\"{test_score.std():.3f}\")\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Skorch doctor"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "from skorch.helper import SkorchDoctor\n",
    "import random\n",
    "\n",
    "torch.manual_seed(0)\n",
    "torch.cuda.manual_seed(0)\n",
    "torch.cuda.manual_seed_all(0)\n",
    "np.random.seed(0)\n",
    "random.seed(0)\n",
    "\n"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Grid search\n"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# More stuff (WIP)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Average difference of 0.007581 with std. dev. of 0.007833.\n"
     ]
    },
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 640x480 with 2 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "from sklearn.datasets import load_iris\n",
    "from matplotlib import pyplot as plt\n",
    "from sklearn.svm import SVC\n",
    "from sklearn.model_selection import GridSearchCV, cross_val_score, KFold\n",
    "import numpy as np\n",
    "\n",
    "# Number of random trials\n",
    "NUM_TRIALS = 30\n",
    "\n",
    "# Load the dataset\n",
    "iris = load_iris()\n",
    "X_iris = iris.data\n",
    "y_iris = iris.target\n",
    "\n",
    "# Set up possible values of parameters to optimize over\n",
    "p_grid = {\"C\": [1, 10, 100], \"gamma\": [0.01, 0.1]}\n",
    "\n",
    "# We will use a Support Vector Classifier with \"rbf\" kernel\n",
    "svm = SVC(kernel=\"rbf\")\n",
    "\n",
    "# Arrays to store scores\n",
    "non_nested_scores = np.zeros(NUM_TRIALS)\n",
    "nested_scores = np.zeros(NUM_TRIALS)\n",
    "\n",
    "# Loop for each trial\n",
    "for i in range(NUM_TRIALS):\n",
    "\n",
    "    # Choose cross-validation techniques for the inner and outer loops,\n",
    "    # independently of the dataset.\n",
    "    # E.g \"GroupKFold\", \"LeaveOneOut\", \"LeaveOneGroupOut\", etc.\n",
    "    inner_cv = KFold(n_splits=4, shuffle=True, random_state=i)\n",
    "    outer_cv = KFold(n_splits=4, shuffle=True, random_state=i)\n",
    "\n",
    "    # Non_nested parameter search and scoring\n",
    "    clf = GridSearchCV(estimator=svm, param_grid=p_grid, cv=outer_cv)\n",
    "    clf.fit(X_iris, y_iris)\n",
    "    non_nested_scores[i] = clf.best_score_\n",
    "\n",
    "    # Nested CV with parameter optimization\n",
    "    clf = GridSearchCV(estimator=svm, param_grid=p_grid, cv=inner_cv)\n",
    "    nested_score = cross_val_score(clf, X=X_iris, y=y_iris, cv=outer_cv)\n",
    "    nested_scores[i] = nested_score.mean()\n",
    "\n",
    "score_difference = non_nested_scores - nested_scores\n",
    "\n",
    "print(\n",
    "    \"Average difference of {:6f} with std. dev. of {:6f}.\".format(\n",
    "        score_difference.mean(), score_difference.std()\n",
    "    )\n",
    ")\n",
    "\n",
    "# Plot scores on each trial for nested and non-nested CV\n",
    "plt.figure()\n",
    "plt.subplot(211)\n",
    "(non_nested_scores_line,) = plt.plot(non_nested_scores, color=\"r\")\n",
    "(nested_line,) = plt.plot(nested_scores, color=\"b\")\n",
    "plt.ylabel(\"score\", fontsize=\"14\")\n",
    "plt.legend(\n",
    "    [non_nested_scores_line, nested_line],\n",
    "    [\"Non-Nested CV\", \"Nested CV\"],\n",
    "    bbox_to_anchor=(0, 0.4, 0.5, 0),\n",
    ")\n",
    "plt.title(\n",
    "    \"Non-Nested and Nested Cross Validation on Iris Dataset\",\n",
    "    x=0.5,\n",
    "    y=1.1,\n",
    "    fontsize=\"15\",\n",
    ")\n",
    "\n",
    "# Plot bar chart of the difference.\n",
    "plt.subplot(212)\n",
    "difference_plot = plt.bar(range(NUM_TRIALS), score_difference)\n",
    "plt.xlabel(\"Individual Trial #\")\n",
    "plt.legend(\n",
    "    [difference_plot],\n",
    "    [\"Non-Nested CV - Nested CV Score\"],\n",
    "    bbox_to_anchor=(0, 1, 0.8, 0),\n",
    ")\n",
    "plt.ylabel(\"score difference\", fontsize=\"14\")\n",
    "\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# # with grid search\n",
    "# from sklearn.model_selection import GridSearchCV\n",
    "\n",
    "# # deactivate skorch-internal train-valid split and verbose logging\n",
    "# net.set_params(train_split=False, verbose=0)\n",
    "# params = {\n",
    "#     'lr': [0.01, 0.02],\n",
    "#     'max_epochs': [10, 20],\n",
    "#     'module__num_units': [100, 1000],\n",
    "# }\n",
    "# gs = GridSearchCV(net, params, refit=False, cv=3, scoring='accuracy', verbose=2)\n",
    "\n",
    "# gs.fit(data, target)\n",
    "# print(\"best score: {:.3f}, best params: {}\".format(gs.best_score_, gs.best_params_))"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Test set"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "ename": "FileNotFoundError",
     "evalue": "[Errno 2] No such file or directory: 'data\\\\data_test.npy'",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mFileNotFoundError\u001b[0m                         Traceback (most recent call last)",
      "Cell \u001b[1;32mIn[19], line 2\u001b[0m\n\u001b[0;32m      1\u001b[0m \u001b[39m# Load data\u001b[39;00m\n\u001b[1;32m----> 2\u001b[0m data_test \u001b[39m=\u001b[39m np\u001b[39m.\u001b[39;49mload(Path(\u001b[39mr\u001b[39;49m\u001b[39m\"\u001b[39;49m\u001b[39mdata/data_test.npy\u001b[39;49m\u001b[39m\"\u001b[39;49m))\n\u001b[0;32m      3\u001b[0m target_test \u001b[39m=\u001b[39m np\u001b[39m.\u001b[39mload(Path(\u001b[39mr\u001b[39m\u001b[39m\"\u001b[39m\u001b[39mdata/target_test.npy\u001b[39m\u001b[39m\"\u001b[39m))\n\u001b[0;32m      5\u001b[0m \u001b[39m# Scale data\u001b[39;00m\n",
      "File \u001b[1;32mc:\\conda\\envs\\learning\\lib\\site-packages\\numpy\\lib\\npyio.py:405\u001b[0m, in \u001b[0;36mload\u001b[1;34m(file, mmap_mode, allow_pickle, fix_imports, encoding, max_header_size)\u001b[0m\n\u001b[0;32m    403\u001b[0m     own_fid \u001b[39m=\u001b[39m \u001b[39mFalse\u001b[39;00m\n\u001b[0;32m    404\u001b[0m \u001b[39melse\u001b[39;00m:\n\u001b[1;32m--> 405\u001b[0m     fid \u001b[39m=\u001b[39m stack\u001b[39m.\u001b[39menter_context(\u001b[39mopen\u001b[39;49m(os_fspath(file), \u001b[39m\"\u001b[39;49m\u001b[39mrb\u001b[39;49m\u001b[39m\"\u001b[39;49m))\n\u001b[0;32m    406\u001b[0m     own_fid \u001b[39m=\u001b[39m \u001b[39mTrue\u001b[39;00m\n\u001b[0;32m    408\u001b[0m \u001b[39m# Code to distinguish from NumPy binary files and pickles.\u001b[39;00m\n",
      "\u001b[1;31mFileNotFoundError\u001b[0m: [Errno 2] No such file or directory: 'data\\\\data_test.npy'"
     ]
    }
   ],
   "source": [
    "# Load data\n",
    "data_test = np.load(Path(r\"data/data_test.npy\"))\n",
    "target_test = np.load(Path(r\"data/target_test.npy\"))\n",
    "\n",
    "# Scale data\n",
    "data_test = StandardScaler3D().fit_transform(data_test)\n",
    "\n",
    "# Reshape X to 1-D for MLP\n",
    "data_test = np.reshape(data_test, (\n",
    "    data_test.shape[0],\n",
    "    data_test.shape[2]*data_test.shape[1]\n",
    "), order=\"F\")\n",
    "\n",
    "plt.plot(data_test[142]);\n",
    "print(f\"{data_test.shape = }\")"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Sklearn implementation\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from sklearn.neural_network import MLPClassifier\n",
    "from sklearn.model_selection import cross_val_score, GroupKFold\n",
    "\n",
    "model = MLPClassifier(\n",
    "    random_state=1, \n",
    "    max_iter=500, \n",
    "    early_stopping=True)\n",
    "\n",
    "cv = GroupKFold()\n",
    "test_score = cross_val_score(model, data, target, groups=groups, cv=cv,\n",
    "                             n_jobs=5)\n",
    "print(f\"The average accuracy is \"\n",
    "      f\"{test_score.mean():.3f} ± \"\n",
    "      f\"{test_score.std():.3f}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "all_scores = pd.DataFrame(\n",
    "    [test_score],\n",
    "    index=[\"KFold with groups\"],\n",
    ").T\n",
    "\n",
    "all_scores.plot.hist(bins=10, edgecolor=\"black\", alpha=0.7)\n",
    "plt.xlabel(\"Accuracy score\")\n",
    "_ = plt.title(\"Distribution of the test scores\")"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Tests"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# test for tranform_to_1d\n",
    "\n",
    "# Reshape X to 1-D for MLP\n",
    "data = np.reshape(data, (\n",
    "    data.shape[0],\n",
    "    data.shape[2]*data.shape[1]\n",
    "), order=\"F\")\n",
    "\n",
    "plt.plot(data[142]);\n",
    "print(f\"{data.shape = }\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from sklearn.model_selection import GroupKFold\n",
    "X = range(100)\n",
    "y = target[:100]\n",
    "groups_ = groups[:1000:10]\n",
    "gkf = GroupKFold(n_splits=6)\n",
    "for train, test in gkf.split(X, y, groups=groups_):\n",
    "    print(\"%s %s\" % (train, test))\n",
    "    print(f\"{train.shape = }\\n{test.shape = }\")"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3.10.8 ('learning')",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.6"
  },
  "orig_nbformat": 4,
  "vscode": {
   "interpreter": {
    "hash": "9b99f9135959a9658cb812fe0ba5c4f69cd3d89b5662a926a2ace19e3111ee69"
   }
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
